package code.whmmm.util.date;


import code.whmmm.util.simple.TimeFormatter;
import code.whmmm.util.simple.ValueWrapper;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * <p><b>
 * 日历 wrapper
 * </b></p>
 * <br/>
 * 创建时间: 2019/9/26 9:22
 *
 * @author Zero
 */
public class CalendarWrapper implements Cloneable {

    public static CalendarWrapper create() {
        return create(new Date());
    }

    public static CalendarWrapper create(Long i) {
        return new CalendarWrapper(new Date(i));
    }

    public static CalendarWrapper create(Date date) {
        return new CalendarWrapper(date);
    }


    private SimpleDateFormat getSimpleDateFormat() {
        return TimeFormatter.STD_DATETIME.getDateFormat();
    }

    /**
     * 内部维护 的 日历实例对象
     */
    private Calendar innerCalendar;

    /**
     * 年 例如 2019
     */
    private String year;
    /**
     * 月份,例如 09
     */
    private String month;

    /**
     * 日期, 例如 08
     */
    private String day;


    /**
     * 24 小时 制, 例如 20
     */
    private String hour;

    /**
     * 分钟 例如 09
     */
    private String minute;

    /**
     * 秒 ,例如 05
     */
    private String second;


    /**
     * 是否 修改过内部 Calendar 对象
     */
    private boolean updated = false;


    /**
     * 根据 {@link Calendar} 实例化 对象
     *
     * @param c 日历对象 {@link Calendar}
     */
    public CalendarWrapper(Calendar c) {

        this.innerCalendar = c;

        evaluate();

    }

    /**
     * 根据当前时间 创建 实例
     */
    public CalendarWrapper() {
        this(new Date());
    }

    public CalendarWrapper(long timestamp) {
        this(new Date(timestamp));
    }

    /**
     * 实例化 对象
     *
     * @param date {@link Date}
     */
    public CalendarWrapper(Date date) {
        this(getCalendar(date));
    }

    /**
     * 更新 内部 日历实例时,需调用此方法为属性重新赋值!!!<br/>
     * 根据 内部维护的 日历对象,重新计算 日/月/年 等属性
     */
    public CalendarWrapper evaluate() {
        // updated = true;
        Date date = innerCalendar.getTime();

        String s = getSimpleDateFormat().format(date);
        String[] s1 = s.split(" ");

        String[] dateArray = s1[0].split("-");

        String[] timeArray = s1[1].split(":");

        year = dateArray[0];
        month = dateArray[1];
        day = dateArray[2];

        hour = timeArray[0];
        minute = timeArray[1];
        second = timeArray[2];

        // 重新对属性赋值后，将修改 标识置换为 false
        updated = false;

        return this;
    }

    /**
     * 结束调用,重新 为 year / month / day 等属性赋值
     * <pre>{@code
     * 已经实现了调用 get 方法自动更新,无需再调用此方法.
     * }</pre>
     *
     * @return {@link CalendarWrapper}
     * @see CalendarWrapper#evaluate()
     */
    @Deprecated
    public CalendarWrapper end() {
        return this.evaluate();
    }


    /**
     * 增加 年数 , 正数为 + (往后算), 负数 为 - (往前算)
     *
     * @param len 要 增加的 年数
     * @return {@link CalendarWrapper}
     */
    public CalendarWrapper addYear(int len) {
        updated = true;
        innerCalendar.set(Calendar.YEAR, innerCalendar.get(Calendar.YEAR) + len);
        return this;
    }


    /**
     * 增加 月份 , 正数为 + (往后算), 负数 为 - (往前算)
     *
     * @param len 要 增加的 月份
     * @return {@link CalendarWrapper}
     */
    public CalendarWrapper addMonth(int len) {
        updated = true;
        innerCalendar.set(Calendar.MONTH, innerCalendar.get(Calendar.MONTH) + len);
        return this;
    }

    /**
     * 增加 天数 , 正数为 + (往后算), 负数 为 - (往前算)
     *
     * @param len 要 增加的 天数
     * @return {@link CalendarWrapper}
     */
    public CalendarWrapper addDay(int len) {
        updated = true;
        innerCalendar.set(Calendar.DAY_OF_MONTH, innerCalendar.get(Calendar.DAY_OF_MONTH) + len);
        return this;
    }


    /**
     * 增加 小时 , 正数为 + (往后算), 负数 为 - (往前算) <br/>
     * 24 小时制 ！！
     *
     * @param len 要 增加的 小时
     * @return {@link CalendarWrapper}
     */
    public CalendarWrapper addHour(int len) {
        updated = true;
        innerCalendar.set(Calendar.HOUR_OF_DAY, innerCalendar.get(Calendar.HOUR_OF_DAY) + len);
        return this;
    }

    /**
     * 增加 分钟 , 正数为 + (往后算), 负数 为 - (往前算)
     *
     * @param len 要 增加的 分钟
     * @return {@link CalendarWrapper}
     */
    public CalendarWrapper addMinute(int len) {
        updated = true;
        innerCalendar.set(Calendar.MINUTE, innerCalendar.get(Calendar.MINUTE) + len);
        return this;
    }

    public CalendarWrapper addSecond(int len) {
        updated = true;
        innerCalendar.set(Calendar.SECOND, innerCalendar.get(Calendar.SECOND) + len);
        return this;
    }

    /**
     * 添加毫秒。
     *
     * @param len
     * @return
     */
    public CalendarWrapper addMillSecond(int len) {
        updated = true;
        innerCalendar.set(Calendar.MILLISECOND, innerCalendar.get(Calendar.MILLISECOND) + len);
        return this;
    }


    public CalendarWrapper setYear(Object year) {
        return setValue(Calendar.YEAR, ValueWrapper.getInt(year));
    }

    public CalendarWrapper setMonth(Object month) {

        return setValue(Calendar.MONTH, ValueWrapper.getInt(month));
    }

    public CalendarWrapper setDay(int day) {

        return setValue(Calendar.DATE, ValueWrapper.getInt(day));
    }

    /**
     * 24 小时制 ！！
     *
     * @param hour
     * @return
     */
    public CalendarWrapper setHour(int hour) {

        return setValue(Calendar.HOUR_OF_DAY, ValueWrapper.getInt(hour));
    }

    public CalendarWrapper setMinute(int minute) {

        return setValue(Calendar.MINUTE, ValueWrapper.getInt(minute));
    }


    public CalendarWrapper setSecond(int second) {

        return setValue(Calendar.SECOND, ValueWrapper.getInt(second));
    }

    /**
     * 设置毫秒数
     *
     * @param millSecond
     * @return
     */
    public CalendarWrapper setMillSecond(int millSecond) {
        return setValue(Calendar.MILLISECOND, ValueWrapper.getInt(millSecond));
    }

    /**
     * 设置值
     *
     * @param calendarType {@link Calendar#DATE}
     * @param len          长度
     * @return CalendarWrapper
     */
    private CalendarWrapper setValue(int calendarType, int len) {
        updated = true;
        innerCalendar.set(calendarType, len);
        return this;
    }


    /**
     * 获取 日历 对象
     *
     * @param date 日期
     * @return {@link Calendar}
     */
    public static Calendar getCalendar(Date date) {
        Calendar calendar = getCalendar();
        calendar.setTime(date);
        return calendar;
    }

    /**
     * 获取 日历 对象
     *
     * @return {@link Calendar}
     */
    public static Calendar getCalendar() {
        return Calendar.getInstance();
    }

    public int getIntYear() {
        return Integer.parseInt(getYear());
    }

    public int getIntMonth() {
        return Integer.parseInt(getMonth());
    }

    public int getIntDay() {
        return Integer.parseInt(getDay());
    }

    public int getIntHour() {
        return Integer.parseInt(getHour());
    }

    public int getIntMinute() {
        return Integer.parseInt(getMinute());
    }

    public int getIntSecond() {
        return Integer.parseInt(getSecond());
    }


    /**
     * 根据内部维护的日历对象,获取 {@link Date}
     *
     * @return Date
     */
    public Date getDate() {
        judgeTime();
        return innerCalendar.getTime();
    }

    /**
     * 根据内部维护的日历对象,获取时间戳
     *
     * @return 毫秒时间戳
     */
    public long getTimestamp() {
        judgeTime();
        return getDate().getTime();
    }


    private void judgeTime() {
        if (updated) {
            // 如果有更新，则重新 设置值。
            evaluate();
            // evaluated() 已经设置了 false， updated = false;
        }
    }

    /**
     * 获取内部日历对象
     *
     * @return
     */
    public Calendar getInnerCalendar() {
        judgeTime();
        return innerCalendar;
    }

    /**
     * 年 例如 2019
     *
     * @return
     */
    public String getYear() {
        judgeTime();
        return year;
    }

    /**
     * 月 例如 06
     *
     * @return
     */
    public String getMonth() {
        judgeTime();
        return month;
    }

    /**
     * 日 例如 09
     *
     * @return
     */
    public String getDay() {
        judgeTime();
        return day;
    }

    /**
     * 小时 例如 08,24 小时制
     *
     * @return
     */
    public String getHour() {
        judgeTime();
        return hour;
    }

    /**
     * 分钟 例如 09 , 45
     *
     * @return
     */
    public String getMinute() {
        judgeTime();
        return minute;
    }

    /**
     * 秒 , 例如 08 ,35
     *
     * @return
     */
    public String getSecond() {
        judgeTime();
        return second;
    }

    /**
     * 国内 周
     * 1--7的值,对应：星期一，星期二，星期三....星期六,星期日，
     *
     * @return
     */
    public int getDayOfWeek() {
        int i = this.getStdDayOfWeek();
        if (i == 0) {
            i = 7;
        } else {
            i = i - 1;
        }
        return i;
    }

    /**
     * java 标准日期 <br/>
     * 1--7的值,对应：星期日，星期一，星期二，星期三....星期六
     *
     * @return
     */
    public int getStdDayOfWeek() {
        judgeTime();
        return innerCalendar.get(Calendar.DAY_OF_WEEK);
    }


    /**
     * 深克隆 {@link CalendarWrapper}, 返回一个新对象！
     *
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    public CalendarWrapper clone() throws CloneNotSupportedException {
        return new CalendarWrapper(new Date(this.getTimestamp()));
    }
}
